<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>CSRF攻击 | yanyan</title>
    <meta name="description" content="Yan&#39;s blog">
    <meta name="generator" content="VuePress 1.4.0">
    <script src="https://cdn.bootcss.com/jquery/3.5.0/jquery.slim.min.js"></script>
  <script src="https://cdn.bootcss.com/fancybox/3.5.7/jquery.fancybox.min.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/fancybox/3.5.7/jquery.fancybox.min.css">
  <link rel="shortcut icon" type="image/x-icon" href="./favicon.ico">
    
    <link rel="preload" href="/assets/css/0.styles.e1b3f17d.css" as="style"><link rel="preload" href="/assets/js/app.e358a08d.js" as="script"><link rel="preload" href="/assets/js/2.88fa18d1.js" as="script"><link rel="preload" href="/assets/js/29.6f108fc9.js" as="script"><link rel="prefetch" href="/assets/js/10.23baf844.js"><link rel="prefetch" href="/assets/js/11.45c148ba.js"><link rel="prefetch" href="/assets/js/12.e5930132.js"><link rel="prefetch" href="/assets/js/13.0547cd14.js"><link rel="prefetch" href="/assets/js/14.3e67795b.js"><link rel="prefetch" href="/assets/js/15.51129890.js"><link rel="prefetch" href="/assets/js/16.6987f89d.js"><link rel="prefetch" href="/assets/js/17.2807cff5.js"><link rel="prefetch" href="/assets/js/18.855e1707.js"><link rel="prefetch" href="/assets/js/19.6da24791.js"><link rel="prefetch" href="/assets/js/20.e24d4aef.js"><link rel="prefetch" href="/assets/js/21.6efc6fba.js"><link rel="prefetch" href="/assets/js/22.10447f0f.js"><link rel="prefetch" href="/assets/js/23.9154cc24.js"><link rel="prefetch" href="/assets/js/24.9ad529fc.js"><link rel="prefetch" href="/assets/js/25.4c092e0a.js"><link rel="prefetch" href="/assets/js/26.debdaa01.js"><link rel="prefetch" href="/assets/js/27.8b90b660.js"><link rel="prefetch" href="/assets/js/28.1a323e01.js"><link rel="prefetch" href="/assets/js/3.7210d3aa.js"><link rel="prefetch" href="/assets/js/30.e7df1937.js"><link rel="prefetch" href="/assets/js/31.2cb3120f.js"><link rel="prefetch" href="/assets/js/32.eb64932c.js"><link rel="prefetch" href="/assets/js/33.cac3e2f0.js"><link rel="prefetch" href="/assets/js/34.19ea35c4.js"><link rel="prefetch" href="/assets/js/35.fadf5d03.js"><link rel="prefetch" href="/assets/js/36.88b681f1.js"><link rel="prefetch" href="/assets/js/37.2a799db9.js"><link rel="prefetch" href="/assets/js/38.2741a2bf.js"><link rel="prefetch" href="/assets/js/39.359ceb72.js"><link rel="prefetch" href="/assets/js/4.9e938666.js"><link rel="prefetch" href="/assets/js/40.56fd4a10.js"><link rel="prefetch" href="/assets/js/41.e72117ad.js"><link rel="prefetch" href="/assets/js/42.63a6e190.js"><link rel="prefetch" href="/assets/js/43.c8072421.js"><link rel="prefetch" href="/assets/js/44.84cd8367.js"><link rel="prefetch" href="/assets/js/45.0ac810b0.js"><link rel="prefetch" href="/assets/js/46.bb83ff34.js"><link rel="prefetch" href="/assets/js/47.a9333a81.js"><link rel="prefetch" href="/assets/js/48.526b5494.js"><link rel="prefetch" href="/assets/js/49.73b61cc6.js"><link rel="prefetch" href="/assets/js/5.88b252c7.js"><link rel="prefetch" href="/assets/js/50.f34ab799.js"><link rel="prefetch" href="/assets/js/51.d06a49d9.js"><link rel="prefetch" href="/assets/js/52.348d5482.js"><link rel="prefetch" href="/assets/js/6.0face56b.js"><link rel="prefetch" href="/assets/js/7.31eca58d.js"><link rel="prefetch" href="/assets/js/8.69e9ce95.js"><link rel="prefetch" href="/assets/js/9.f25df9e1.js">
    <link rel="stylesheet" href="/assets/css/0.styles.e1b3f17d.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">yanyan</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <!----></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><!---->  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><a href="/html/001" class="sidebar-heading clickable"><span>HTML</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/css/image" class="sidebar-heading clickable"><span>CSS</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/js/001" class="sidebar-heading clickable"><span>JS-基础</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/js-v8/001" class="sidebar-heading clickable"><span>JS-V8引擎原理 </span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/js-async/001" class="sidebar-heading clickable"><span>JS-异步I/O及异步编程</span> <span class="arrow right"></span></a> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/http/000" class="sidebar-heading clickable open"><span>HTTP</span> <span class="arrow down"></span></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/http/001.html" class="sidebar-link">01 HTTP 的特点？HTTP 的缺点</a></li><li><a href="/http/002.html" class="sidebar-link">02 说一说从输入URL到页面呈现发生了什么？——网络篇</a></li><li><a href="/http/003.html" class="sidebar-link">03 说一说从输入URL到页面呈现发生了什么？——解析算法篇</a></li><li><a href="/http/004.html" class="sidebar-link">04 说一说从输入URL到页面呈现发生了什么？——渲染过程篇</a></li><li><a href="/http/005.html" class="sidebar-link">05 谈谈你对重绘和回流的理解</a></li><li><a href="/http/006.html" class="sidebar-link">06 XSS攻击</a></li><li><a href="/http/007.html" class="active sidebar-link">07 CSRF攻击</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/http/007.html#什么是csrf攻击？" class="sidebar-link">什么是CSRF攻击？</a></li><li class="sidebar-sub-header"><a href="/http/007.html#防范措施" class="sidebar-link">防范措施</a></li><li class="sidebar-sub-header"><a href="/http/007.html#总结" class="sidebar-link">总结</a></li></ul></li><li><a href="/http/008.html" class="sidebar-link">08 (传统RSA版本)HTTPS为什么让数据传输更安全</a></li><li><a href="/http/009.html" class="sidebar-link">09 Https TLS 1.2  1.3</a></li><li><a href="/http/010.html" class="sidebar-link">10 Cookie</a></li><li><a href="/http/011.html" class="sidebar-link">11 什么是跨域？浏览器如何拦截响应？如何解决</a></li><li><a href="/http/012.html" class="sidebar-link">12 Http2</a></li><li><a href="/http/013.html" class="sidebar-link">13 Http缓存</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><a href="/extend/002" class="sidebar-heading clickable"><span>拓展阅读</span> <span class="arrow right"></span></a> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="csrf攻击"><a href="#csrf攻击" class="header-anchor">#</a> CSRF攻击</h1> <h2 id="什么是csrf攻击？"><a href="#什么是csrf攻击？" class="header-anchor">#</a> 什么是CSRF攻击？</h2> <p>CSRF(Cross-site request forgery), 即跨站请求伪造，指的是黑客诱导用户点击链接，打开黑客的网站，然后黑客利用用户目前的登录状态发起跨站请求。</p> <p>举个例子, 你在某个论坛点击了黑客精心挑选的小姐姐图片，你点击后，进入了一个新的页面。</p> <p>那么恭喜你，被攻击了:）</p> <p>你可能会比较好奇，怎么突然就被攻击了呢？接下来我们就来拆解一下当你点击了链接之后，黑客在背后做了哪些事情。</p> <p>可能会做三样事情。列举如下：</p> <ol><li>自动发 GET 请求
黑客网页里面可能有一段这样的代码:</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token operator">&lt;</span>img src<span class="token operator">=</span><span class="token string">&quot;https://xxx.com/info?user=hhh&amp;count=100&quot;</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>img<span class="token operator">&gt;</span>
</code></pre></div><p>进入页面后自动发送 get 请求，值得注意的是，这个请求会自动带上关于 <a href="http://xxx.com" target="_blank" rel="noopener noreferrer">xxx.com<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> 的 cookie 信息(这里是假定你已经在 <a href="http://xxx.com" target="_blank" rel="noopener noreferrer">xxx.com<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a> 中登录过)。</p> <p>假如服务器端没有相应的验证机制，它可能认为发请求的是一个正常的用户，因为携带了相应的 cookie，然后进行相应的各种操作，可以是转账汇款以及其他的恶意操作</p> <ol start="2"><li>自动发 POST 请求</li></ol> <p>黑客可能自己填了一个表单，写了一段自动提交的脚本。</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">'</span>hacker-form<span class="token punctuation">'</span></span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>https://xxx.com/info<span class="token punctuation">&quot;</span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>POST<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>hidden<span class="token punctuation">&quot;</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>user<span class="token punctuation">&quot;</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>hhh<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>hidden<span class="token punctuation">&quot;</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>count<span class="token punctuation">&quot;</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>100<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'hacker-form'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">submit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>同样也会携带相应的用户 cookie 信息，让服务器误以为是一个正常的用户在操作，让各种恶意的操作变为可能。</p> <ol start="3"><li>诱导点击发送 GET 请求
在黑客的网站上，可能会放上一个链接，驱使你来点击:</li></ol> <div class="language-html extra-class"><pre class="language-html"><code><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>https://xxx/info?user=hhh&amp;count=100<span class="token punctuation">&quot;</span></span> <span class="token attr-name">taget</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>_blank<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>点击进入修仙世界<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><p>点击后，自动发送 get 请求，接下来和自动发 GET 请求部分同理。</p> <p>这就是CSRF攻击的原理。和XSS攻击对比，CSRF 攻击并不需要将恶意代码注入用户当前页面的html文档中，而是跳转到新的页面，利用服务器的验证漏洞和用户之前的登录状态来模拟用户进行操作。</p> <h2 id="防范措施"><a href="#防范措施" class="header-anchor">#</a> 防范措施</h2> <h3 id="_1-利用cookie的samesite属性"><a href="#_1-利用cookie的samesite属性" class="header-anchor">#</a> 1.利用Cookie的SameSite属性</h3> <p>CSRF攻击中重要的一环就是自动发送目标站点下的 Cookie,然后就是这一份 Cookie 模拟了用户的身份。因此在Cookie上面下文章是防范的不二之选。</p> <p>恰好，在 Cookie 当中有一个关键的字段，可以对请求中 Cookie 的携带作一些限制，这个字段就是SameSite。</p> <p>SameSite可以设置为三个值，Strict、Lax和None。</p> <p>a. 在Strict模式下，浏览器完全禁止第三方请求携带Cookie。比如请求sanyuan.com网站只能在sanyuan.com域名当中请求才能携带 Cookie，在其他网站请求都不能。</p> <p>b. 在Lax模式，就宽松一点了，但是只能在 get 方法提交表单况或者a 标签发送 get 请求的情况下可以携带 Cookie，其他情况均不能。 (chrome 80后Lax为默认)</p> <p>c. 在None模式下，也就是默认模式，请求会自动携带上 Cookie。 (chrome 80前为默认)</p> <p><a href="/html/010.html">关于cookie</a></p> <h3 id="_2-验证来源站点"><a href="#_2-验证来源站点" class="header-anchor">#</a> 2. 验证来源站点</h3> <p>这就需要要用到请求头中的两个字段: Origin和Referer。</p> <p>其中，Origin只包含域名信息，而Referer包含了具体的 URL 路径。</p> <p>当然，这两者都是可以伪造的，通过 Ajax 中自定义请求头即可，安全性略差。</p> <h3 id="_3-csrf-token"><a href="#_3-csrf-token" class="header-anchor">#</a> 3. CSRF Token</h3> <p>Django作为 Python 的一门后端框架，用它开发过的同学就知道，在它的模板(template)中, 开发表单时，经常会附上这样一行代码:</p> <div class="language- extra-class"><pre class="language-text"><code>{% csrf_token %}
</code></pre></div><p>这就是CSRF Token的典型应用。那它的原理是怎样的呢？</p> <p>首先，浏览器向服务器发送请求时，服务器生成一个字符串，将其植入到返回的页面中。</p> <p>然后浏览器如果要发送请求，就必须带上这个字符串，然后服务器来验证是否合法，如果不合法则不予响应。这个字符串也就是CSRF Token，通常第三方站点无法拿到这个 token, 因此也就是被服务器给拒绝。</p> <h2 id="总结"><a href="#总结" class="header-anchor">#</a> 总结</h2> <p>CSRF(Cross-site request forgery), 即跨站请求伪造，指的是黑客诱导用户点击链接，打开黑客的网站，然后黑客利用用户目前的登录状态发起跨站请求。
CSRF攻击一般会有三种方式:</p> <ol><li>自动 GET 请求</li> <li>自动 POST 请求</li> <li>诱导点击发送 GET 请求。</li></ol> <p>防范措施: 利用 Cookie 的 SameSite 属性、验证来源站点和CSRF Token。</p></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/http/006.html" class="prev">
        06 XSS攻击
      </a></span> <span class="next"><a href="/http/008.html">
        08 (传统RSA版本)HTTPS为什么让数据传输更安全
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/assets/js/app.e358a08d.js" defer></script><script src="/assets/js/2.88fa18d1.js" defer></script><script src="/assets/js/29.6f108fc9.js" defer></script>
  </body>
</html>
